﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;

using Flagwind.Text;
using Flagwind.IO;

namespace Flagwind.Storages.Web
{
    internal static class Utility
    {
        private static readonly TextRegular ImageRegex = new TextRegular(@"^([^\.]*\.)+(jpg|jpeg|gif|bmp|png|ico)$");
		private static readonly Regex ImageSizeRegex = new Regex(@"^(\S*)_(?<width>\d+)[xX](?<height>\d+)(\.)(jpg|jpeg|gif|bmp|png|ico)$");
		private static readonly Regex TailorImageSizeRegex = new Regex(@"^(\S*)_(?<width>\d+)[xX](?<height>\d+)([xX](?<thumb>\d+)([xX](?<site>\d+))?)?(\.)(jpg|jpeg|gif|bmp|png|ico)$");
		private static readonly Regex OriginalImageRegex = new Regex(@"_\d+[xX]\d+([xX]\d+([xX]\d+)?)?");

        public static bool IsImagePath(string path)
        {
            return ImageRegex.IsMatch(path);
        }

		public static string EnsureImageSize(string path, out int? width, out int? height)
		{
			width = null;
			height = null;

			Path result = null;

			if(Path.TryParse(path, out result))
			{
				var match = ImageSizeRegex.Match(path);

				if(match.Success)
				{
					width = Flagwind.Common.Convert.ConvertValue<int>(match.Groups["width"].Value);
					height = Flagwind.Common.Convert.ConvertValue<int>(match.Groups["height"].Value);

					var originalFileName = OriginalImageRegex.Replace(result.FileName, string.Empty);
					var originalFilePath = Path.Combine(result.DirectoryName, originalFileName);

					return originalFilePath;
				}
			}

			return path;
		}

		public static string EnsureImageSize(string path, out int? width, out int? height, out int? thumb, out int? site)
		{
			width = null;
			height = null;
			thumb = null;
			site = null;

			Path result = null;

			if(Path.TryParse(path, out result))
			{
				var match = TailorImageSizeRegex.Match(path);

				if(match.Success)
				{
					width = Flagwind.Common.Convert.ConvertValue<int>(match.Groups["width"].Value);
					height = Flagwind.Common.Convert.ConvertValue<int>(match.Groups["height"].Value);

					thumb = Flagwind.Common.Convert.ConvertValue<int>(match.Groups["thumb"].Value);
					site = Flagwind.Common.Convert.ConvertValue<int>(match.Groups["site"].Value);

					var originalFileName = OriginalImageRegex.Replace(result.FileName, string.Empty);
					var originalFilePath = Path.Combine(result.DirectoryName, originalFileName);

					return originalFilePath;
				}
			}

			return path;
		}

		public static string EnsureImagePath(string directory, string extension, int width, int height)
        {
            return Flagwind.IO.Path.Combine(directory, string.Format("{0}_{1}{2}", width, height, extension));
        }

		public static string EnsureImagePath(string directory, string extension, int width, int height, int thumb, int site)
		{
			return Flagwind.IO.Path.Combine(directory, string.Format("{0}_{1}_{2}_{3}{4}", width, height, thumb, site, extension));
		}

		public static string EnsureImageDirectory(string path)
        {
            var original = Flagwind.IO.Path.Parse(path.Remove(path.LastIndexOf(".", StringComparison.Ordinal)) + "/");

            return original.FullPath;
        }

        public static ImageFormat EnsureImageFormat(string mediaType)
        {
            switch (mediaType)
            {
                case "image/jpg": return ImageFormat.Jpeg;
                case "image/jpeg": return ImageFormat.Jpeg;
                case "image/gif": return ImageFormat.Gif;
                case "image/png": return ImageFormat.Png;
                case "image/bmp": return ImageFormat.Bmp;
                case "image/x-icon": return ImageFormat.Icon;
            }

            return ImageFormat.Jpeg;
        }

        public static Image GetReducedImage(int width, int height, Image imageFrom)
        {
            // 源图宽度及高度 
            var imageFromWidth = imageFrom.Width;
            var imageFromHeight = imageFrom.Height;

            // 生成的缩略图实际宽度及高度.如果指定的高和宽比原图大，则返回原图；否则按照指定高宽生成图片
            if (width >= imageFromWidth && height >= imageFromHeight)
            {
                return imageFrom;
            }
            else
            {
                // 生成的缩略图在上述"画布"上的位置
                var x = 0;
                var y = 0;

                // 创建画布
                var bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
                bitmap.SetResolution(imageFrom.HorizontalResolution, imageFrom.VerticalResolution);

                using (var g = Graphics.FromImage(bitmap))
                {
                    // 用白色清空 
                    g.Clear(Color.White);

                    // 指定高质量的双三次插值法。执行预筛选以确保高质量的收缩。此模式可产生质量最高的转换图像。 
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

                    // 指定高质量、低速度呈现。 
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.CompositingQuality = CompositingQuality.HighQuality;

                    // 在指定位置并且按指定大小绘制指定的 Image 的指定部分。 
                    g.DrawImage(imageFrom, new Rectangle(x, y, width, height), new Rectangle(0, 0, imageFromWidth, imageFromHeight), GraphicsUnit.Pixel);

                    return bitmap;
                }
            }
        }

		/// <summary>
		/// 能等比缩放就缩放，不能就裁剪
		/// </summary>
		/// <param name="width">宽度</param>
		/// <param name="height">高度</param>
		/// <param name="thumb">0 缩放；1 裁剪(能等比缩放就缩放)；2 强制裁剪 </param>
		/// <param name="site">位置0左边；1中间；2右边</param>
		/// <param name="imageFrom"></param>
		/// <returns></returns>
		public static Image GetReducedImage(int width, int height, int thumb, int site, Image imageFrom)
		{
			switch(thumb)
			{
				case 1:
					{
						// 取得比例系数   
						float w = imageFrom.Width / (float)width;
						float h = imageFrom.Height / (float)height;

						// 能等比缩放就缩放，不能就裁剪
						if(w == h)
							return GetReducedImage(width, height, imageFrom);
						else
							return GetTailorImage(width, height, site, imageFrom);
					}
				case 2:
					{
						// 强制裁剪图片
						return GetTailorImage(width, height, site, imageFrom);
					}
				default:
					{
						// 默认缩放
						return GetReducedImage(width, height, imageFrom);
					}
			}
		}

		/// <summary>
		/// 强制裁剪图片
		/// </summary>
		/// <param name="width">宽度</param>
		/// <param name="height">高度</param>
		/// <param name="site">位置0左边；1中间；2右边</param>
		/// <param name="imageFrom"></param>
		/// <returns></returns>
		public static Image GetTailorImage(int width, int height, int site, Image imageFrom)
		{
			// 源图宽度及高度 
			var imageFromWidth = imageFrom.Width;
			var imageFromHeight = imageFrom.Height;

			// 生成的缩略图实际宽度及高度.如果指定的高和宽比原图大，则返回原图；否则按照指定高宽生成图片
			if(width >= imageFromWidth && height >= imageFromHeight)
			{
				return imageFrom;
			}
			else
			{
				width = width >= imageFromWidth ? imageFromWidth : width;
				height = height >= imageFromHeight ? imageFromHeight : height;

				//默认裁剪坐标
				int cutX = (imageFromWidth - width) / 2;
				int cutY = (imageFromHeight - height) / 2;

				switch(site)
				{
					case 1:
					{
						cutX = 0;
						cutY = 0;
						break;
					}
					case 2:
					{
						cutX = imageFromWidth - width;
						cutY = 0;
						break;
					}
				}

				// 生成的缩略图在上述"画布"上的位置
				var x = 0;
				var y = 0;

				// 创建画布
				var bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
				bitmap.SetResolution(imageFrom.HorizontalResolution, imageFrom.VerticalResolution);

				using(var g = Graphics.FromImage(bitmap))
				{
					// 用白色清空 
					g.Clear(Color.White);

					// 指定高质量的双三次插值法。执行预筛选以确保高质量的收缩。此模式可产生质量最高的转换图像。 
					g.InterpolationMode = InterpolationMode.HighQualityBicubic;

					// 指定高质量、低速度呈现。 
					g.SmoothingMode = SmoothingMode.HighQuality;
					g.CompositingQuality = CompositingQuality.HighQuality;

					// 在指定位置并且按指定大小绘制指定的 Image 的指定部分。 
					g.DrawImage(imageFrom, new Rectangle(x, y, width, height), new Rectangle(cutX, cutY, width, height), GraphicsUnit.Pixel);

					return bitmap;
				}
			}
		}
	}
}
